--
-- DESCRIPTION
--
-- @COMPANY **
-- @AUTHOR **
-- @DATE ${date} ${time}
--

---@type BP_King_C
local M = UnLua.Class("Climber.Blueprints.Characters.BP_PlatformChar")

local KismetSystemLibrary = UE.UKismetSystemLibrary

-- 游戏模式
local GameModeClass = UE.UClass.Load("/Script/Engine.Blueprint'/TowerClimber/Blueprints/GM_Platformer.GM_Platformer_C'")

-- 走出平面即将坠落的定时器
local WalkingOffLedgeTime = UE.FTimerHandle()

-- 掉落定时器
local DropTime = UE.FTimerHandle()

-- 跳跃缓冲定时器
local JumpBuffering = UE.FTimerHandle()

-- 键盘输入的2D轴
local InputVector2D = UE.FVector2D()

-- function M:Initialize(Initializer)
-- end

-- function M:UserConstructionScript()
-- end

function M:ReceiveBeginPlay()
    self.CapsuleComponent.OnComponentBeginOverlap:Add(self, self.OnComponentBeginOverlap_CapsuleComponent)
end

-- function M:ReceiveEndPlay()
-- end

function M:ReceiveTick(DeltaSeconds)
    -- self.Super.ReceiveTick(self)

    if self.IsDefeated == false then
        self:TraceForPlatforms()

        -- 判断是否有跳跃的按键缓存
        if self.IsJumpBuffering and self:CanJump() and self:GetVelocity().Z <= 0 then
            self:Jump()
        end
    end
end

-- function M:ReceiveAnyDamage(Damage, DamageType, InstigatedBy, DamageCauser)
-- end

-- function M:ReceiveActorBeginOverlap(OtherActor)
-- end

-- function M:ReceiveActorEndOverlap(OtherActor)
-- end

-- 重写被击败
function M:Defeat()
    self.Super.Defeat(self)
    self:UnBindingInput()
    self.SpringArm:K2_DetachFromComponent(UE.EDetachmentRule.KeepWorld, UE.EDetachmentRule.KeepWorld, UE.EDetachmentRule.KeepWorld, true)
    UE.UGameplayStatics.PlaySound2D(self, self.PlayerDefeated)

    local ShakeClass = UE.UClass.Load("/Script/Engine.Blueprint'/TowerClimber/CameraShake/CS_Defeated.CS_Defeated_C'")

    UE.UGameplayStatics.PlayWorldCameraShake(self, ShakeClass, self:K2_GetActorLocation(), 0, 1000, 1, false)

    KismetSystemLibrary.K2_SetTimerDelegate({ self, self.RestartCharacter }, 3, false)

end

function M:OnComponentBeginOverlap_CapsuleComponent(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, FromSweep, SweepResult)

    local BP_PigClass = UE.UClass.Load("/Script/Engine.Blueprint'/TowerClimber/Blueprints/Characters/Pig/BP_Pig.BP_Pig_C'")

    local Pig = OtherActor:Cast(BP_PigClass)
    if Pig then
        local TempVelocity = self:GetVelocity()
        self.CapsuleComponent:GetScaledCapsuleHalfHeight()
        if self.CharacterMovement:IsFalling() and TempVelocity.Z < 0 and self:K2_GetActorLocation().Z > Pig:K2_GetActorLocation().Z + Pig.CapsuleComponent:GetScaledCapsuleHalfHeight() then
            Pig:Defeat()
            self:LaunchCharacter(UE.FVector(0, 0, self.EnemyBounceLaunch), false, true)
        else
            self:Defeat()
        end
    end
end

function M:JumpPressed()
    if self:CanJump() then
        if InputVector2D.Y >= 0 then
            self:Jump()
        else
            self:SetCapsuleOverlap()
            self.CanDrop = true

            if KismetSystemLibrary:K2_IsTimerActiveHandle(DropTime) then
                KismetSystemLibrary:K2_UnPauseTimerHandle(DropTime)
            else
                DropTime = KismetSystemLibrary.K2_SetTimerDelegate({ self, self.StopDrop }, 0.15, false)
            end

        end
    else
        --- 把跳跃储存在缓冲里面，一定时间内会自动触发跳跃
        self.IsJumpBuffering = true
        if KismetSystemLibrary:K2_IsTimerActiveHandle(JumpBuffering) then
            KismetSystemLibrary:K2_PauseTimerHandle(JumpBuffering)
            KismetSystemLibrary:K2_ClearTimerHandle(JumpBuffering)
        else
            JumpBuffering = KismetSystemLibrary.K2_SetTimerDelegate({ self, self.SetIsJumpBuffering }, self.JumpBufferLength, false)
        end
    end
end

function M:JumpReleased()
    self:StopJumping()
end

-- 可以跳跃
function M:CanJumpInternal()
    return self.Overridden.CanJumpInternal(self) or self.IsInCoyoteTime
end

-- 设置跳跃缓冲结束
function M:SetIsJumpBuffering()
    self.IsJumpBuffering = false
end

-- 当角色离开表面并即将下落时触发事件
function M:OnWalkingOffLedge(PreviousFloorImpactNormal, PreviousFloorContactNormal, PreviousLocation, TimeDelta)
    self.IsInCoyoteTime = true

    if KismetSystemLibrary:K2_IsTimerActiveHandle(WalkingOffLedgeTime) then
        KismetSystemLibrary:K2_PauseTimerHandle(WalkingOffLedgeTime)
        KismetSystemLibrary:K2_ClearTimerHandle(WalkingOffLedgeTime)
    else
        WalkingOffLedgeTime = KismetSystemLibrary.K2_SetTimerDelegate({ self, self.SetCoyoteTime }, self.CoyoteTimeLength, false)
    end
end

-- 设置下落可以跳跃的时间结束
function M:SetCoyoteTime()
    self.IsInCoyoteTime = false
    KismetSystemLibrary:K2_PauseTimerHandle(WalkingOffLedgeTime)
    KismetSystemLibrary:K2_ClearTimerHandle(WalkingOffLedgeTime)
end

-- 停止可以下落（通常是停止可以穿过单向的平台）
function M:StopDrop()
    self.CanDrop = false
end

function M:Move(Value)
    local Value2D = UE.UEnhancedInputLibrary.Conv_InputActionValueToAxis2D(Value)

    if self.CharacterMovement:IsFalling() == false then
        InputVector2D = Value2D
    end

    self:AddMovementInput(UE.FVector(1, 0, 0), Value2D.X, false)
    self:UpdateControllerRotation()
end

function M:AttackPressed()
    if self.InAttack then
        return
    end

    self.InAttack = true
    self:Attack()

    UE.UKismetSystemLibrary.K2_SetTimerDelegate({ self, self.EndOfAttack }, 0.15, false)

end
function M:AttackReleased()

end

function M:EndOfAttack()
    self.InAttack = false
end

function M:MoveCompleted(Value)
    InputVector2D = UE.FVector2D(0, 0)
end

--  更新控制器旋转
function M:UpdateControllerRotation()

    local Controller = self:GetController()
    local Rotation = UE.FRotator()

    if Controller == nil then
        return
    end

    if self.CharacterMovement.Velocity.X > 0 then
        Rotation.Yaw = 0
        Controller:SetControlRotation(Rotation)
    end

    if self.CharacterMovement.Velocity.X < 0 then
        Rotation.Yaw = 180
        Controller:SetControlRotation(Rotation)
    end
end

-- 追踪平台
function M:TraceForPlatforms()

    -- self.Overridden.TraceForPlatforms(self)

    if self.CharacterMovement:IsFalling() and self.CanDrop == false then
        local StartLocation = self.FootPosition:K2_GetComponentLocation()
        local EndLocation = StartLocation - UE.FVector(0, 0, 10)

        local HitResult = UE.FHitResult()

        local Hit = UE.UKismetSystemLibrary.BoxTraceSingleForObjects(
                self,
                EndLocation,
                EndLocation,
                UE.FVector(32, 32, 10),
                UE.FRotator(),
                self.PlatformsCollisionType,
                false,
                UE.TArray(UE.AActor),
                UE.EDrawDebugTrace.None,
                HitResult,
                true,
                UE.FLinearColor(1, 0, 0, 1), UE.FLinearColor(0, 1, 0, 1), 0.1
        )

        if Hit and self:GetVelocity().Z < 0 then
            self:SetCapsuleBlock()
        else
            self:SetCapsuleOverlap()
        end
    end

end

-- 重新开始关卡
function M:RestartLevel()
    local LevelName = UE.UGameplayStatics.GetCurrentLevelName(self)
    UE.UGameplayStatics.OpenLevel(self, LevelName)
end

-- 死亡重生
function M:RestartCharacter()
    local ControllerRef = self:GetController()
    self:K2_DestroyActor()

    local PlayerStarts = UE.TArray(UE.APlayerStart)

    UE.UGameplayStatics.GetAllActorsOfClass(self, UE.APlayerStart, PlayerStarts)

    self.GameMode = UE.UGameplayStatics.GetGameMode(self):Cast(GameModeClass)

    self.GameMode:PlayerDied(ControllerRef, PlayerStarts:Get(UE.UKismetMathLibrary.RandomInteger64InRange(1, PlayerStarts:Length())))

end

-- 设置胶囊体平台碰撞开启
function M:SetCapsuleBlock()
    self.CapsuleComponent:SetCollisionResponseToChannel(UE.ECollisionChannel.OneWayPlatform, UE.ECollisionResponse.ECR_Block)
end

-- 设置胶囊体平台重叠开启
function M:SetCapsuleOverlap()
    self.CapsuleComponent:SetCollisionResponseToChannel(UE.ECollisionChannel.OneWayPlatform, UE.ECollisionResponse.ECR_Overlap)
end

return M
